package com.mingda.weathermagiccenter.task;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mingda.weathermagiccenter.config.LegendHumiConfig;
import com.mingda.weathermagiccenter.config.LegendPrecConfig;
import com.mingda.weathermagiccenter.config.LegendTemConfig;
import com.mingda.weathermagiccenter.config.LegendWindConfig;
import com.mingda.weathermagiccenter.config.LegendPresConfig;
import com.mingda.weathermagiccenter.config.hefengconfig.WeatherConfigBean;
import com.mingda.weathermagiccenter.pojo.WsEquisurfaceData;
import com.mingda.weathermagiccenter.pojo.WsEquisurfaceOrg;
import com.mingda.weathermagiccenter.service.ISdtProjectService;
import com.mingda.weathermagiccenter.service.WsEquisurfaceDataService;
import com.mingda.weathermagiccenter.service.WsEquisurfaceOrgService;
import com.mingda.weathermagiccenter.service.WsStationDataService;
import com.mingda.weathermagiccenter.utils.WeatherDataProcessor;
import com.mingda.weathermagiccenter.utils.WeatherDataProcessor.ProcessedWeatherData;
import com.mingda.weathermagiccenter.utils.lzugis.geotools.EquiSurface;

import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.ssssssss.magicapi.core.service.MagicAPIService;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

//@Tag(name = "dzm", description = "dzm")
//@RestController
//@RequestMapping("/weathergeojson")

@Configuration
@Slf4j

@Async
@EnableScheduling
@ConditionalOnProperty(prefix = "weathergeojson",name = "enabled",havingValue = "true")
public class InsertGeoJsonTask {

    @Value("${weathergeojson.shape:}")
    private String shape;
    @Value("${weathergeojson.source:}")
    private String source;  // '1':国家站 '2':区域站 '3':火险监测站(海康) '4':和风 '':全部
    @Value("${weathergeojson.isclip:}")
    private Boolean isclip;  // 是否裁切

    // 建议将HttpClient设为全局单例，避免频繁创建
    private static final HttpClient CLIENT = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(30))
            .build();
    
    @Autowired
    MagicAPIService service;
    @Autowired
    WsEquisurfaceDataService wsEquisurfaceDataService;
    @Autowired
    WsEquisurfaceOrgService wsEquisurfaceOrgService;
    @Autowired
    WsStationDataService wsStationDataService;
    @Autowired
    private WeatherConfigBean configBean;
    @Autowired
    ISdtProjectService iSdtProjectService;

   // @GetMapping("getgeo")
 //   @Scheduled(cron = "${weathergeojson.cron}")
    public void geojsontask() {
        log.info("");

        Map<String, Object> params = new HashMap<>();
        // 注入变量信息
        params.put("orgid","220");
        params.put("stationtype","1"); //国家站数据
        // 内部调用接口不包含code以及message信息，同时也不走拦截器。
        HashMap value = service.execute("GET", "/mdweatherapi/wsstationweatherlegend", params);
        List<LinkedHashMap<String, Object>> list = (List<LinkedHashMap<String, Object>>) value.get("data");
        List<HashMap<String, Object>> temp = (List<HashMap<String, Object>>) value.get("legendtemall");
        if(StringUtils.isNotBlank(source)){
            String[] sources = source.split(",");
            System.out.println("source: " + sources.length);
        }

        JSONArray legend = (JSONArray) JSONArray.toJSON(temp);
        //List<TrainDataVO> tempDatas = new ArrayList<>();
        //LsosurfaceUtil.generatePictureByName(tempDatas, "1", shape,"220");
    }


    //@GetMapping("getgeo")
    //@Scheduled(cron = "${weathergeojson.cron}")
    public void geometrytask() {
        //天气类别：temp：温度，prec：降雨，humi：湿度，pres：气压，wind：风力
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("temp", "温度");
        jsonObject.put("prec", "降雨");
        jsonObject.put("humi", "湿度");
        jsonObject.put("pres", "气压");
        jsonObject.put("wind", "风力");
        //  获取所有组织边界
        List<WsEquisurfaceOrg> orgs = wsEquisurfaceOrgService.getListGeometry();
        for(WsEquisurfaceOrg org : orgs) {
            String orgid = org.getOrgid();
            String orgname = org.getOrgname();
            String geojson = (String) org.getOrgGeom(); //边界数据
            // 遍历 jsonObject
            for (String key : jsonObject.keySet()) {
                String value = jsonObject.getString(key);
                //System.out.println("天气类型: " + key + "，中文名称: " + value);
                if(StringUtils.isNotBlank(source)){ //处理多个来源
                    String[] sources = source.split(",");
                    // 使用逗号分隔字符串并遍历
                    for (String s : sources) {
                        createDZMData(orgid, orgname, geojson, key, value, s);
                    }
                }else{
                    createDZMData(orgid, orgname, geojson, key, value, source);
                }

                
            }
        }
    }


//  生成等值面数据
    public void createDZMData(String orgid, String orgname, String geojson, String wtype, String wname, String mysource) {
        long startTime = System.currentTimeMillis(); // 记录开始时间
        log.info(orgname+"：开始生成等值面数据（" + wname + "）:" + startTime);
        // 获取天气数据
        Date date = new Date();
        // 定义日期格式
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:00:00");
        String d = formatter.format(date);

        // 预先获取目标字段的键名，避免在每次过滤时重复计算
        String fieldKey = switch (wtype) {
            case "temp" -> "temp";
            case "prec" -> "prec";
            case "humi" -> "humi";
            case "pres" -> "pres";
            case "wind" -> "win_10_vel";
            default -> "temp";
        };

        Map<String, Object> params = new HashMap<>();
        // 注入变量信息
        if(orgid.length()>3){
            params.put("orgid",orgid.substring(0, 3));
        }else{
            params.put("orgid",orgid);
        }

        if("0".equals(mysource)){
            mysource="";
        }
        params.put("stationtype",mysource);
        // 内部调用接口不包含code以及message信息，同时也不走拦截器。
        HashMap value = service.execute("GET", "/mdweatherapi/wsstationweatherlegend", params);
        List<LinkedHashMap<String, Object>> list = (List<LinkedHashMap<String, Object>>) value.get("data");
        log.info("过滤前数据条数："+list.size()+"");
        AtomicInteger counter = new AtomicInteger(0); // 使用原子类确保线程安全
        list = list.stream()
            .filter(data -> {

                Float val = convertToFloat(data.get(fieldKey));
                return val != null && val != 999999;

                // Object v = data.get(fieldKey);
                // if (v == null) {
                //     return false;
                // }
                // Float val = convertToFloat(v);
                // int i = counter.getAndIncrement(); // 自增计数器
                // log.info(fieldKey+"-"+i+"-value: " + val);
                // if (val == null || val.equals(999999.0f)) {
                //     return false;
                // }
                // if ("temp".equals(wtype) && (val < -50 || val > 60)) {
                //     return false;
                // }
                // if ("prec".equals(wtype) && (val < 0 || val > 300)) {
                //     return false;
                // }
                // if ("humi".equals(wtype) && (val < 0 || val > 100)) {
                //     return false;
                // }
                // if ("pres".equals(wtype) && (val < 800 || val > 1200)) {
                //     return false;
                // }
                // if ("wind".equals(wtype) && (val < 0 || val > 50)) {
                //     return false;
                // }

                // return true;
            })
            .collect(Collectors.toList());
            
        int length = list.size();
        log.info("过滤后数据条数："+length+"");
        if(length<=0){
            log.info(orgname+"："+wname+"数据为空！不能生成等值面。");
            log.info("--------------------------------------------------------------------------------");
            return;
        }
		double[][] trainData = new double[3][length];
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> data = list.get(i);
            // 提取每个字段
            String stationkey = (String) data.get("stationkey"); 
            Float lon = (Float) data.get("lon");
            Float lat = (Float) data.get("lat");
            Float alt = (Float) data.get("alt");
            String stationname = (String) data.get("stationname");
            Float val = 0.0f;

            if("temp".equals(wtype)){
                val = (Float) data.get("temp");
            }else if("prec".equals(wtype)){
                val = (Float) data.get("prec");
            }else if("humi".equals(wtype)){
                val = (Float) data.get("humi");
            }else if ("pres".equals(wtype)) {
                val = (Float) data.get("pres");
            }else if ("wind".equals(wtype)) {
                val = (Float) data.get("win_10_vel");
            }else{
                val = (Float) data.get("temp");
            }

            trainData[0][i] = lon;
            trainData[1][i] = lat;
            trainData[2][i] = val;
        }
        // 获取图例
        JSONArray legend = null;
        if("temp".equals(wtype)){
            //List<LegendTemConfig> temp  = configBean.getLegendtem();
            List<HashMap<String, Object>> temp = (List<HashMap<String, Object>>) value.get("legendtemall");
            legend = (JSONArray) JSONArray.toJSON(temp);
        }else if("prec".equals(wtype)){
            //List<LegendPrecConfig> prec  = configBean.getLegendprec();
            List<HashMap<String, Object>> prec = (List<HashMap<String, Object>>) value.get("legendprec");
            legend = (JSONArray) JSONArray.toJSON(prec);
        }else if("humi".equals(wtype)){
            //List<LegendHumiConfig> humi  = configBean.getLegendhumi();
            List<HashMap<String, Object>> humi = (List<HashMap<String, Object>>) value.get("legendhumi");
            legend = (JSONArray) JSONArray.toJSON(humi);
        }else if ("pres".equals(wtype)) {
            //List<LegendPresConfig> pres  = configBean.getLegendpres();
            List<HashMap<String, Object>> pres = (List<HashMap<String, Object>>) value.get("legendpres");
            legend = (JSONArray) JSONArray.toJSON(pres);
        }else if ("wind".equals(wtype)) {
            //List<LegendWindConfig> wind  = configBean.getLegendwind();
            List<HashMap<String, Object>> wind = (List<HashMap<String, Object>>) value.get("legendwind");
            legend = (JSONArray) JSONArray.toJSON(wind);
        }else{
            //List<LegendTemConfig> temp  = configBean.getLegendtem();
            List<HashMap<String, Object>> temp = (List<HashMap<String, Object>>) value.get("legendtemall");
            legend = (JSONArray) JSONArray.toJSON(temp);
        }

        EquiSurface equiSurface = new EquiSurface();
 
        double[] dataInterval = null;

        int[] size = new int[]{length, length};

        //boolean isclip = true; //是否裁切
        if(StringUtils.isBlank(geojson)){
            isclip = false;
        }
        
        String strJson = equiSurface.calEquiSurface_geojson(trainData, dataInterval, size, geojson, legend, isclip, wname);

        if(StringUtils.isNotBlank(strJson)){
            //保存数据
            WsEquisurfaceData wsEquisurfaceData = new WsEquisurfaceData();
            String id = java.util.UUID.randomUUID().toString();
            wsEquisurfaceData.setId(id);
            wsEquisurfaceData.setGeom(strJson);
            wsEquisurfaceData.setFlag("1");
            wsEquisurfaceData.setWdate(d);
            wsEquisurfaceData.setWtype(wtype);
            wsEquisurfaceData.setOrgid(orgid);
            wsEquisurfaceData.setOrgname(orgname);
            // String wsource = "全部";
            // if("1".equals(mysource)){
            //     wsource = "国家站";
            // }else if("2".equals(mysource)){
            //     wsource = "区域站";
            // }else if("3".equals(mysource)){
            //     wsource = "火险监测站(海康)";
            // }else if("4".equals(mysource)){
            //     wsource = "和风";
            // }
            if (StringUtils.isBlank(mysource)) {
                mysource = "0";
            }
            wsEquisurfaceData.setWsource(mysource);
            wsEquisurfaceData.setLegend(legend.toJSONString());
            wsEquisurfaceDataService.saveWsEquisurfaceData(wsEquisurfaceData);
        }
        long endTime = System.currentTimeMillis(); // 记录结束时间
        double durationInSeconds = (double) ((endTime - startTime) / (1000)); // 计算耗时（秒）
        log.info(orgname+"：结束生成等值面数据（" + wname + "），共用时：" + durationInSeconds + " 秒");
        log.info("--------------------------------------------------------------------------------");
    }

    //  生成等值面数据
    public void createDZMDataBak(String orgid, String orgname, String geojson, String wtype, String wname) {
        long startTime = System.currentTimeMillis(); // 记录开始时间
        log.info(orgname+"：开始生成等值面数据（" + wname + "）:" + startTime);
        // 获取天气数据
        Date date = new Date();
        // 定义日期格式
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:00:00");
        String d = formatter.format(date);

        // 预先获取目标字段的键名，避免在每次过滤时重复计算
        String fieldKey = switch (wtype) {
            case "temp" -> "temp";
            case "prec" -> "prec";
            case "humi" -> "humi";
            case "pres" -> "pres";
            case "wind" -> "win_10_vel";
            default -> "temp";
        };
        List<Map<String, Object>> list = wsStationDataService.getWsStationData(orgid, source, d).stream()
            .filter(data -> {
                Float val = convertToFloat(data.get(fieldKey));
                return val != null && val != 999999;
                // if (val  == null && val == 999999) {
                //     return false;
                // }
                // // 过滤温度不合格数据
                // if ("temp".equals(wtype) && (val < -50 || val > 60)) {
                //     return false; // 温度超出有效范围时排除该数据
                // }
                // // 过滤降雨量不合格数据
                // if ("prec".equals(wtype) && (val < 0 || val > 300)) {
                //     return false;
                // }
                // // 过滤湿度不合格数据
                // if ("humi".equals(wtype) && (val < 0 || val > 100)) {
                //     return false;
                // }
                // // 过滤气压不合格数据
                // if ("pres".equals(wtype) && (val < 800 || val > 1200)) {
                //     return false;
                // }
                // // 过滤风力不合格数据
                // if ("wind".equals(wtype) && (val < 0 || val > 50)) {
                //     return false;
                // }
                // return true;
            })
            .collect(Collectors.toList());
            
        int length = list.size();
        if(length<=0){
            log.info(orgname+"："+wname+"数据为空！不能生成等值面。");
            return;
        }
		double[][] trainData = new double[3][length];
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> data = list.get(i);
            // 提取每个字段
            String stationkey = (String) data.get("stationkey"); 
            Float lon = (Float) data.get("lon");
            Float lat = (Float) data.get("lat");
            Float alt = (Float) data.get("alt");
            String stationname = (String) data.get("stationname");
            Float val = 0.0f;

            if("temp".equals(wtype)){
                val = (Float) data.get("temp");
            }else if("prec".equals(wtype)){
                val = (Float) data.get("prec");
            }else if("humi".equals(wtype)){
                val = (Float) data.get("humi");
            }else if ("pres".equals(wtype)) {
                val = (Float) data.get("pres");
            }else if ("wind".equals(wtype)) {
                val = (Float) data.get("win_10_vel");
            }else{
                val = (Float) data.get("temp");
            }

            trainData[0][i] = lon;
            trainData[1][i] = lat;
            trainData[2][i] = val;
        }
        // 获取图例
        JSONArray legend = null;
        if("temp".equals(wtype)){
            List<LegendTemConfig> temp  = configBean.getLegendtem();
            legend = (JSONArray) JSONArray.toJSON(temp);
        }else if("prec".equals(wtype)){
            List<LegendPrecConfig> temp  = configBean.getLegendprec();
            legend = (JSONArray) JSONArray.toJSON(temp);
        }else if("humi".equals(wtype)){
            List<LegendHumiConfig> temp  = configBean.getLegendhumi();
            legend = (JSONArray) JSONArray.toJSON(temp);
        }else if ("pres".equals(wtype)) {
            List<LegendPresConfig> temp  = configBean.getLegendpres();
            legend = (JSONArray) JSONArray.toJSON(temp);
        }else if ("wind".equals(wtype)) {
            List<LegendWindConfig> temp  = configBean.getLegendwind();
            legend = (JSONArray) JSONArray.toJSON(temp);
        }else{
            List<LegendTemConfig> temp  = configBean.getLegendtem();
            legend = (JSONArray) JSONArray.toJSON(temp);
        }

        EquiSurface equiSurface = new EquiSurface();
 
        double[] dataInterval = null;

        int[] size = new int[]{length, length};

        //boolean isclip = true; //是否裁切
        if(StringUtils.isBlank(geojson)){
            isclip = false;
        }
        
        String strJson = equiSurface.calEquiSurface_geojson(trainData, dataInterval, size, geojson, legend, isclip, wname);

        //if(StringUtils.isNoneBlank(strJson)){
            //保存数据
            WsEquisurfaceData wsEquisurfaceData = new WsEquisurfaceData();
            String id = java.util.UUID.randomUUID().toString();
            wsEquisurfaceData.setId(id);
            wsEquisurfaceData.setGeom(strJson);
            wsEquisurfaceData.setFlag("1");
            wsEquisurfaceData.setWdate(d);
            wsEquisurfaceData.setWtype(wtype);
            wsEquisurfaceData.setOrgid(orgid);
            wsEquisurfaceData.setOrgname(orgname);
            String wsource = "全部";
            if("1".equals(source)){
                wsource = "国家站";
            }else if("2".equals(source)){
                wsource = "区域站";
            }else if("3".equals(source)){
                wsource = "火险监测站(海康)";
            }
            wsEquisurfaceData.setWsource(wsource);
            wsEquisurfaceDataService.saveWsEquisurfaceData(wsEquisurfaceData);
        //}
        long endTime = System.currentTimeMillis(); // 记录结束时间
        double durationInMinutes = (double) ((endTime - startTime) / (60*1000)); // 计算耗时（分）
        log.info(orgname+"：结束生成等值面数据（" + wname + "），共用时：" + durationInMinutes + " 分");
    }

    // 单独封装转换方法
    private Float convertToFloat(Object valObj) {
        if (valObj instanceof Number num) return num.floatValue();
        if (valObj instanceof String str) {
            try {
                return Float.parseFloat(str);
            } catch (NumberFormatException ignored) {}
        }
        return null;
    }

    private Double convertToDouble(Object valObj) {
        if (valObj instanceof Number num) {
            return num.doubleValue();
        }
        if (valObj instanceof String str) {
            try {
                return Double.parseDouble(str);
            } catch (NumberFormatException ignored) {}
        }
        return null;
    }

     //测试用单线程
    //@GetMapping("getpythongeo")
    //@Async
    //@Scheduled(cron = "${weathergeojson.cron}")
    public void geometrytaskpython() {
        //天气类别：
        // temp：温度，prec：降雨，humi：湿度，pres：气压，wind：风力，
        // waterrate：土壤含水率，waterrate_out_plant：地表覆盖物表面湿度，waterrate_inside_plant：地表覆盖物内部湿度
        // rainfall12hour：12小时降雨量，rainfall24hour：24小时降雨量，rainfall10day：10日降雨量，rainfall3month：3个月降雨量
        // winddeck：风场
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        // jsonObject.put("temp", "温度");
        // jsonObject.put("prec", "降雨量");
        // jsonObject.put("humi", "湿度");
        // jsonObject.put("pres", "气压");
        // jsonObject.put("wind", "风力");
        // jsonObject.put("waterrate", "土壤含水率");
        // jsonObject.put("waterrateout", "地表覆盖物表面湿度");
        // jsonObject.put("waterrateinside", "地表覆盖物内部湿度");
        // jsonObject.put("rainfall12hour", "12小时降雨量");
        // jsonObject.put("rainfall24hour", "24小时降雨量");
        // jsonObject.put("rainfall10day", "10日降雨量");
        jsonObject.put("rainfall3month", "3个月降雨量");
        // jsonObject.put("winddeck", "风场");

        //  获取项目列表
        List<Map<String, Object>> projects = iSdtProjectService.getSdtProjectList();
        
        for (Map<String, Object> project : projects) {
            String projectid = project.get("id").toString();
            String orgname = project.get("name").toString();
            String orgid = project.get("f1").toString();
            String bjno = "1"; // 默认边界编号1：吉林省
            // 遍历天气类型
            for (String key : jsonObject.keySet()) {
                String value = jsonObject.getString(key);
                
                if (StringUtils.isNotBlank(source)) {
                    String[] sources = source.split(",");
                    for (String s : sources) {
                        createPythonDZMData(orgid, orgname, key, value, s, projectid, bjno);
                    }
                } else {
                    createPythonDZMData(orgid, orgname, key, value, source, projectid, bjno);
                }
            }
        }
    }

    //多线程版本
    //@GetMapping("getpythongeo")
    @Async
    @Scheduled(cron = "${weathergeojson.cron}")
    public void geometrytaskpythonThread() {
        //天气类别：
        // temp：温度，prec：降雨，humi：湿度，pres：气压，wind：风力，
        // waterrate：土壤含水率，waterrate_out_plant：地表覆盖物表面湿度，waterrate_inside_plant：地表覆盖物内部湿度
        // rainfall12hour：12小时降雨量，rainfall24hour：24小时降雨量，rainfall10day：10日降雨量，rainfall3month：3个月降雨量
        // winddeck：风场
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        jsonObject.put("temp", "温度");
        jsonObject.put("prec", "降雨量");
        jsonObject.put("humi", "湿度");
        jsonObject.put("pres", "气压");
        jsonObject.put("wind", "风力");
        jsonObject.put("waterrate", "土壤含水率");
        jsonObject.put("waterrateout", "地表覆盖物表面湿度");
        jsonObject.put("waterrateinside", "地表覆盖物内部湿度");
        jsonObject.put("rainfall12hour", "12小时降雨量");
        jsonObject.put("rainfall24hour", "24小时降雨量");
        jsonObject.put("rainfall10day", "10日降雨量");
        jsonObject.put("rainfall3month", "3个月降雨量");
        jsonObject.put("winddeck", "风场");

        //  获取项目列表
        List<Map<String, Object>> projects = iSdtProjectService.getSdtProjectList();
        
        // 创建合理大小的线程池（建议根据CPU核心数或IO密集型任务特点设置）
        // 建议优化为基于系统资源的动态配置
        // int threadPoolSize = Math.min(projects.size() * jsonObject.size(), 
        //     Runtime.getRuntime().availableProcessors() * 1);
        // 推荐：基于CPU核心数但更保守的设置 最多使用CPU核心数的1/4， 至少有1个线程在运行， 不会超过实际需要处理的任务总数，
        int threadPoolSize = Math.min(
            Math.max(1, Runtime.getRuntime().availableProcessors() / 4),
            projects.size() * jsonObject.size()
        );
        log.info("创建线程池，大小: " + threadPoolSize);
        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
        
        // 收集所有任务
        List<Runnable> tasks = new ArrayList<>();
        
        for (Map<String, Object> project : projects) {
            String projectid = project.get("id").toString();
            String orgname = project.get("name").toString();
            String orgid = project.get("f1").toString();
            String bjno = "1"; // 默认边界编号1：吉林省
            // 遍历天气类型
            for (String key : jsonObject.keySet()) {
                String value = jsonObject.getString(key);
                
                if (StringUtils.isNotBlank(source)) {
                    String[] sources = source.split(",");
                    for (String s : sources) {
                        tasks.add(() -> createPythonDZMData(orgid, orgname, key, value, s, projectid, bjno));
                    }
                } else {
                    tasks.add(() -> createPythonDZMData(orgid, orgname, key, value, source, projectid, bjno));
                }
            }
        }
        
        // 批量提交所有任务
        List<java.util.concurrent.Future<?>> futures = new ArrayList<>();
        for (Runnable task : tasks) {
            futures.add(executorService.submit(task));
        }
        
        // 关闭线程池并等待所有任务完成
        executorService.shutdown();
        try {
            // 等待所有任务完成
            for (java.util.concurrent.Future<?> future : futures) {
                future.get(); // 可设置超时时间
            }
        } catch (Exception e) {
            log.error("执行任务时发生异常", e);
        }
        
    }

    //  生成等值面数据——python版本
    public void createPythonDZMData(String orgid, String orgname, String wtype, String wname, String mysource, String projectid, String bjno) {
        long startTime = System.currentTimeMillis(); // 记录开始时间
        log.info("开始生成python等值面数据（" + wname + "）:" + startTime);
        // 获取天气数据
        Date date = new Date();
        // 定义日期格式
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:00:00");
        String d = formatter.format(date);

        Map<String, Object> params = new HashMap<>();
        // 注入变量信息
        if(orgid.length()>3){
            params.put("orgid",orgid.substring(0, 3));
        }else{
            params.put("orgid",orgid);
        }

        if("0".equals(mysource)){
            mysource="";
        }
        params.put("stationtype",mysource);
        // 内部调用接口不包含code以及message信息，同时也不走拦截器。
        HashMap value = new HashMap();
        if(wtype.startsWith("rainfall")) {
            // 获取累计降雨量数据
            Map<String, String> timeRange = WeatherDataProcessor.getljtime(wtype);
            params.put("btime", timeRange.get("btime"));
            params.put("etime", timeRange.get("etime"));
            value = service.execute("GET", "/mdweatherapi/wsprec", params);

        }else{
            value = service.execute("GET", "/mdweatherapi/wsstationweatherlegendcur", params);
        }
        
		ProcessedWeatherData processedWeatherData = WeatherDataProcessor.setDataByType(value, wtype);

        JSONArray weatherData = processedWeatherData.weatherData;

        JSONArray legend = processedWeatherData.legend;

        JSONArray interval = processedWeatherData.interval;

        //打印日志
        //log.info("orgid:"+orgid+"，orgname:"+orgname+"，wtype:"+wtype+"，wname:"+wname+"，mysource:"+mysource+"，projectid:"+projectid);
        log.info("weatherData:"+weatherData.size());
        log.info("legend:"+legend.size());
        log.info("interval:"+interval.size());

        if(weatherData.size()==0||legend.size()==0||interval.size()==0){
            log.info("没有数据，请检查数据源！");
            return;
        }

        String strJson = "";
        String geom = "";

        if(wtype.startsWith("winddeck")) {
            //请求python服务，获取风场geojson数据
            strJson = requestWindDeckService(weatherData, bjno, wname);
            JSONObject jsonObject = JSONObject.parseObject(strJson);
            JSONObject geonjson = jsonObject.getJSONObject("wind_data");
            geom = geonjson.toJSONString();
        }else{
            //请求python服务，获取等值面geojson数据
            strJson = requestPythonService(weatherData, interval, bjno, wname);
            JSONObject jsonObject = JSONObject.parseObject(strJson);
            JSONObject geonjson = jsonObject.getJSONObject("geojson");
            geom = geonjson.toJSONString();
        }

        if(StringUtils.isNotBlank(geom)){
            //保存数据
            WsEquisurfaceData wsEquisurfaceData = new WsEquisurfaceData();
            String id = java.util.UUID.randomUUID().toString();
            wsEquisurfaceData.setId(id);
            wsEquisurfaceData.setGeom(geom);
            wsEquisurfaceData.setFlag("1");
            wsEquisurfaceData.setWdate(d);
            wsEquisurfaceData.setWtype(wtype);
            wsEquisurfaceData.setOrgid(orgid);
            wsEquisurfaceData.setOrgname(orgname);
            // String wsource = "全部";
            // if("1".equals(mysource)){
            //     wsource = "国家站";
            // }else if("2".equals(mysource)){
            //     wsource = "区域站";
            // }else if("3".equals(mysource)){
            //     wsource = "火险监测站(海康)";
            // }else if("4".equals(mysource)){
            //     wsource = "和风";
            // }
            if (StringUtils.isBlank(mysource)) {
                mysource = "0";
            }
            wsEquisurfaceData.setWsource(mysource);
            wsEquisurfaceData.setLegend(legend.toJSONString());
            wsEquisurfaceData.setProjectid(projectid);
            wsEquisurfaceDataService.saveWsEquisurfaceData(wsEquisurfaceData);
        }
        long endTime = System.currentTimeMillis(); // 记录结束时间
        double durationInSeconds = (double) ((endTime - startTime) / (1000)); // 计算耗时（秒）
        log.info("结束生成等值面数据（" + wname + "），共用时：" + durationInSeconds + " 秒");
        log.info("--------------------------------------------------------------------------------");
    }


    // 获取等值面geojson数据
    private String requestPythonService(JSONArray weatherData, JSONArray interval, String bjno, String wname) {
        String url = "https://www.mdyjsx.cn:6001/dzm100/generate-isosurface";
        String strJson = "";
        
        String clusterDistance = "4.0";
        if("10日降雨量".equals(wname) || "3个月降雨量".equals(wname)) {
            clusterDistance = "0.0";
        }
        
        try {
            // 构建请求参数
            JSONObject requestBody = new JSONObject();
            requestBody.put("data_file", weatherData);
            requestBody.put("legend_file", interval);
            requestBody.put("org_id", bjno);
            requestBody.put("data_type", wname);
            requestBody.put("cluster_distance", clusterDistance);
            
            // 创建 HttpRequest
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(requestBody.toJSONString()))
                    .build();
            
            // 发送请求并获取响应
            HttpResponse<String> response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
            
            if (response.statusCode() == 200) {
                strJson = response.body();
                log.info("成功获取等值面数据，数据长度: " + (strJson != null ? strJson.length() : 0));
            } else {
                log.error("请求Python服务失败，状态码: " + response.statusCode());
            }
        } catch (Exception e) {
            log.error("请求Python服务异常: ", e);
        }
        
        return strJson;
    }

    // 获取风场geojson数据
    private String requestWindDeckService(JSONArray weatherData, String bjno, String wname) {
        String url = "https://www.mdyjsx.cn:6001/dzm100/generate-wind-field";
        String strJson = "";
        
        try {
            // 构建请求参数
            JSONObject requestBody = new JSONObject();
            requestBody.put("data", weatherData);
            requestBody.put("bj", bjno);
            
            // 创建 HttpRequest
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(requestBody.toJSONString()))
                    .build();
            
            // 发送请求并获取响应
            HttpResponse<String> response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
            
            if (response.statusCode() == 200) {
                strJson = response.body();
                log.info("成功获取风场数据，数据长度: " + (strJson != null ? strJson.length() : 0));
            } else {
                log.error("请求Python服务失败，状态码: " + response.statusCode());
            }
        } catch (Exception e) {
            log.error("请求Python服务异常: ", e);
        }
        
        return strJson;
    }


}
